﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using BOMS.Lib.Net;

namespace BOMS.TcpClient
{

    public partial class FormTcpClient : Form
    {

        TcpCli cli = new TcpCli();

        #region             SetText 委托的实现
        //声明委托：用于跨越线程设置文本框的内容
        public delegate void SetTextControlCallBack(string text, int type, bool appendOrSet, Control control);
        //使能控件
        public delegate void SetControlEnableCallBack(Control control, bool isEnable);
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 设置控件内容
        /// </summary>
        /// <param name="text">字符串</param>
        /// <param name="type">文本框的类型0--Control，1--TextBox</param>
        /// <param name="appendOrSet">是追加还是赋值 true-表示追加  false-表示赋值</param>
        /// <param name="control">控件</param>
        ///-----------------------------------------------------------------*
        private void SetTextControl(string text,
            int type, bool appendOrSet, Control control)
        {
            //如果调用方位于创建该控件线程以外的线程时，需要获取是否要调用Invoke方法
            if (control.InvokeRequired)
            {
                SetTextControlCallBack setTextCallBack = new SetTextControlCallBack(SetTextControl);
                control.Invoke(setTextCallBack, new object[] { text, type, appendOrSet, control });
            }
            else //如果不是线程外的调用时：设置文本框的值
            {
                if (appendOrSet == true)
                {
                    control.Text += text;
                }
                else
                {
                    control.Text = text;
                }
                if (type == 0)
                {
                    control.Text = "";
                    control.Text = text;
                }
                else if (type == 1)
                {
                    control.Text += "\r\n";
                    //设置滚动位置
                    ((TextBox)control).SelectionStart = ((TextBox)control).TextLength;
                    ((TextBox)control).ScrollToCaret();//滚动到当前光标位置
                    ((TextBox)control).SelectionLength = 0;

                }
                control.Refresh();
            }
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 使能控件
        /// </summary>
        /// <param name="control"></param>
        /// <param name="isEnable"></param>
        ///-----------------------------------------------------------------*
        private void SetControlEnable( Control control,bool isEnable)
        {
            //如果调用方位于创建该控件线程以外的线程时，需要获取是否要调用Invoke方法
            if (control.InvokeRequired)
            {
                SetControlEnableCallBack SetControlEnableCallBack = new SetControlEnableCallBack(SetControlEnable);
                control.Invoke(SetControlEnableCallBack, new object[] { control, isEnable });
            }
            else //如果不是线程外的调用时：设置文本框的值
            {
                control.Enabled = isEnable;
            }
        }
        #endregion
        /// <summary>
        /// 初始化窗体，添加事件
        /// </summary>
        ///-----------------------------------------------------------------*
        public FormTcpClient()
        {
            InitializeComponent();
            //添加事件
            cli.Resovlver = new DatagramResolver("##");

            cli.ReceivedDatagram += new NetEvent(this.RecvData);

            cli.DisConnectedServer += new NetEvent(this.ClientClose);

            cli.ConnectedServer += new NetEvent(this.ClientConn);

            //设置地址框中的IP和端口
            string HostName = Dns.GetHostName();//获得主机名
            IPHostEntry hostIp;
            //hostIp = Dns.GetHostEntry(HostName);//根据主机名获取主机信息
            hostIp = Dns.GetHostByName(HostName); 
            //将获取的IP信息和端口显示在客户端
            this.textBoxSrvIP.Text = hostIp.AddressList[0].ToString();
            this.textBoxSrvPort.Text = "1238";
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 连接到服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        private void buttonConn_Click(object sender, EventArgs e)
        {
            string srvIP = this.textBoxSrvIP.Text.ToLower();
            string srvPort = this.textBoxSrvPort.Text.ToLower();
            try
            {
                if (srvIP != "" && srvPort != "")
                {
                    if (cli.IsConnected == false)
                    {
                        cli.Connect(srvIP, int.Parse(srvPort));
                        
                    }
                    if (cli.IsConnected == true)
                    {
                        SetTextControl("TCP已连接", 0, true, this.labelState);
                    }
                    else
                    {
                        SetTextControl("TCP连接失败", 0, true, this.labelState);
                    }
                }
                else
                {
                    SetTextControl("命令错误", 0, true, this.labelState);
                }
            }
            catch
            {
                SetTextControl("服务器无相应", 0, true, this.labelState);
            }
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        private void buttonClose_Click(object sender, EventArgs e)
        {
            try
            {
                if (cli.IsConnected == true)
                {
                    cli.Close();
                    SetControlEnable(this.textBoxSrvIP, true);
                    SetControlEnable(this.textBoxSrvPort, true);
                    SetControlEnable(this.buttonConn, true);//显示连接按钮
                    SetControlEnable(this.buttonClose, false);//不显示关闭按钮
                    SetTextControl("连接已关闭", 0, true, this.labelState);

                }
                else
                {
                    SetTextControl("未连接到服务器", 0, true, this.labelState);
                }
            }
            catch
            {
                SetTextControl("当前无连接", 0, true, this.labelState);
            }
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        private void buttonSndData_Click(object sender, EventArgs e)
        {
            //加上结束标志##
           // string dataToSnd = this.textBoxSndData.Text.ToLower()+"##";
            string dataToSnd = this.textBoxSndData.Text.Trim();
            try
            {
                if (cli.IsConnected == true)
                {
                    Byte[] data = Convert2ByteArrayFromHexString(dataToSnd);
                    cli.Send(data); //发送数据
                    SetTextControl("已发送数据", 0, true, this.labelState);
                }
                else
                {
                    SetTextControl("未连接到服务器", 0, true, this.labelState);
                }
            }
            catch
            {
                SetTextControl("服务器主动拒绝访问", 0, true, this.labelState);
            }

        }
        private byte[] Convert2ByteArrayFromHexString(string input)
        {
            string[] arr = input.Trim().Split(' ');
            byte[] data = new byte[arr.Length];
            for (int i = 0; i < arr.Length; i++)
            {
                data[i] = (Byte)Convert.ToInt32(arr[i], 16);
            }
            return data;
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 退出程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        private void buttonExit_Click(object sender, EventArgs e)
        {
            //清理资源
            cli.Close();
            this.Dispose();
            this.Close();
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 清空数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        private void buttonClearData_Click(object sender, EventArgs e)
        {
            this.textBoxSndData.Text = "";
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 清空发回信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        private void buttonClearIfo_Click(object sender, EventArgs e)
        {
            this.textBoxFeedBack.Text = "";
        }

        #region 定义TCP客户端事件
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 客户端连接事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        void ClientConn(object sender, NetEventArgs e)
        {
            string info = string.Format("A Client:{0} connect server :{1}", e.Client,
            e.Client.ClientSocket.RemoteEndPoint.ToString());
            SetTextControl(info, 1, true, this.textBoxFeedBack);
            SetTextControl("请求连接成功", 0, true, this.labelState);
            SetControlEnable(this.textBoxSrvIP, false);
            SetControlEnable(this.textBoxSrvPort, false);
            SetControlEnable(this.buttonConn, false);
            SetControlEnable(this.buttonClose, true);
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 客户端关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        void ClientClose(object sender, NetEventArgs e)
        {
            string info;

            if (e.Client.TypeOfExit == Session.ExitType.ExceptionExit)
            {
                info = string.Format("A Client Session:{0} Exception Closed.", e.Client.ID);
            }
            else
            {
                info = string.Format("A Client Session:{0} Normal Closed.", e.Client.ID);
            }
            cli.Close();//关闭连接
            SetTextControl(info, 1, true, this.textBoxFeedBack);
            SetControlEnable(this.buttonConn,true);
        }
        ///-----------------------------------------------------------------*
        /// <summary>
        /// 收到数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        ///-----------------------------------------------------------------*
        void RecvData(object sender, NetEventArgs e)
        {
            string rcvData = e.Client.Datagram;
            string dataToShow = rcvData.Substring(0,rcvData.Length-2);
            string info = string.Format("recv data:{0} from:{1}.", dataToShow, e.Client);
            SetTextControl(info, 1, true, this.textBoxFeedBack);
        }

        #endregion


    }
}